#include "ObserverSituationInterface.hpp"

#include "WsfTrack.hpp"
#include "WsfGroundMover.hpp"
#include "WsfAirMover.hpp"
#include "WsfSurfaceMover.hpp "
#include "WsfWaypoint.hpp"
#include "sensor/WsfSensor.hpp"
#include "WsfPlatform.hpp"
#include "WsfTrackManager.hpp"
#include "WsfSimulation.hpp"

ObserverControlInterface::ObserverControlInterface()
{
    
}

ObserverControlInterface::InterfaceError ObserverControlInterface::DecodeMsg(std::string msg)
{
    // 处理外部消息
    // 首先对数据进行反序列化
    Json::Reader reader;
    Json::Value data;

    if (!reader.parse(msg, data))
        return InterfaceError(-1, "reader_error");
    try
    {
        std::string msgType = data["MsgType"].asString();

        ut::log::info() << "zhanglei:recv msg: " << msgType;

        if (msgType == "SimStart")
            return HandleMsg_Start(data);

        if (msgType == "SimPause")
            return HandleMsg_Pause(data);

        if (msgType == "SimResume")
            return HandleMsg_Resume(data);

        if (msgType == "SimComplete")
            return HandleMsg_Complete(data);

        if (msgType == "PlatformLocationChange")
            return HandleMsg_LocationChange(data);

        if (msgType == "SimAdvanceTime")
            return HandleMsg_SimAdvanceTime(data);

        if (msgType == "SimClockRate")
            return HandleMsg_SimClockRate(data);

        if (msgType == "PlatformMoveTo")
            return HandleMsg_MoveTo(data);

        if (msgType == "AttackTarget")
            return HandleMsg_AttackTarget(data);

        if (msgType == "ControlSensor")
            return HandleMsg_ControlSensor(data);
    }
    catch (std::exception &e)
    {
        std::cout << "request format error:" << e.what() << std::endl;
        return InterfaceError(-1, "equest format error");
    }
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_Pause(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();

    if (simulation.GetState() == WsfSimulation::State::cACTIVE)
        simulation.Pause();
    return InterfaceError(1, "SimulationPauseFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_Resume(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();

    if (simulation.GetState() == WsfSimulation::State::cACTIVE)
        simulation.Resume();
    return InterfaceError(1, "SimulationResumeFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_Start(Json::Value &data)
{
    GetSimulation().Start();
    return InterfaceError(1, "SimulationStartFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_Complete(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    simulation.Complete(simulation.GetWallTime());
    return InterfaceError(1, "SimulationCompleteFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_LocationChange(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    int pid = data["PlatformID"].asInt();
    std::vector<double> loc;
    Json::Value locj = data["Location"];

    for (int i = 0; i < locj.size(); i++)
    {
        Json::Value element = locj[i];
        loc.push_back(element.asDouble());
    }

    if (loc.size() >= 3)
    {
        WsfPlatform *pptr = simulation.GetPlatformByIndex(pid);

        if (!pptr)
            return InterfaceError(-1, "LocationChangeError_GetPlatFormError");

        WsfMover *mvptr = pptr->GetMover();

        if (!mvptr)
            return InterfaceError(-1, "LocationChangeError_GetMoverError");

        pptr->SetLocationLLA(loc[0], loc[1], loc[2]);
        ut::log::info() << "mover";
        mvptr->ResetPosition(simulation.GetWallTime());
    }
    return InterfaceError(1, "SimulationLocationChangeFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_MoveTo(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    int pid = data["PlatformID"].asInt();
    WsfPlatform *pptr = simulation.GetPlatformByIndex(pid);
    if (!pptr)
        return InterfaceError(-1, "MoveToError_GetPlatFormError");

    Json::Value waypointData = data["WayPoint"];
    if (!waypointData.isArray() || waypointData.size() < 3)
        return InterfaceError(-1, "MoveToError_WaypointDataError");

    // 提取WayPoint参数
    double lat = waypointData[0].asDouble(); // 纬度
    double lon = waypointData[1].asDouble(); // 经度
    double alt = waypointData[2].asDouble(); // 海拔
    pptr->GetMover()->GoToLocation(simulation.GetWallTime(), lat, lon, alt);
    return InterfaceError(1, "SimulationMoveToFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_Speed(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    int pid = data["PlatformID"].asInt();
    WsfPlatform *pptr = simulation.GetPlatformByIndex(pid);
    if (!pptr)
        return InterfaceError(-1, "SpeedError_GetPlatFormError");
    ;

    Json::Value waypointData = data["Speed"];
    double spd = data["Speed"].asDouble();       // 速度
    double acc = data["LinearAccel"].asDouble(); // 速度
    pptr->GetMover()->GoToSpeed(simulation.GetWallTime(), spd, acc, false);
    return InterfaceError(1, "SimulationSpeedFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_SimClockRate(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    double cRate = data["ClockRate"].asDouble();
    simulation.SetClockRate(cRate);
    return InterfaceError(1, "SimulationClockRateFinish");
    ;
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_SimAdvanceTime(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    double advTime = data["AdvanceTime"].asDouble();
    simulation.AdvanceTime(simulation.GetWallTime() + advTime);
    return InterfaceError(1, "SimulationAdvanceTimeFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_AttackTarget(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    int pid = data["PlatformID"].asInt();
    WsfPlatform *pptr = simulation.GetPlatformByIndex(pid);
    if (!pptr)
        return InterfaceError(-1, "AttackTargetError_GetPlatFormError");

    // 获取轨迹
    unsigned int localTrackCount = pptr->GetTrackManager().GetTrackCount();
    unsigned int rawTrackCount = pptr->GetTrackManager().GetRawTrackCount();
    ut::log::info() << "localTrackCount: " << localTrackCount;
    ut::log::info() << "rawTrackCount: " << rawTrackCount;
    if (localTrackCount < 1 && rawTrackCount < 1)
        return InterfaceError(-1, "AttackTargetError_NoTrack");
    WsfTrack *track = pptr->GetTrackManager().GetTrackEntry(localTrackCount - 1);

    // 武器
    std::string weaponId = data["WeaponID"].asString();
    WsfWeapon *weapon = static_cast<WsfWeapon *>(pptr->FindComponent(weaponId));
    if (!weapon)
        return InterfaceError(-1, "AttackTargetError_NoWeapon");
    ut::log::info() << "weaponinfo: " << weapon->GetWeaponEffectsType();

    weapon->CueToTarget(GetSimulation().GetWallTime(), track);
    WsfWeapon::FireTarget fireTarget = WsfWeapon::FireTarget(track);
    WsfWeapon::FireOptions fireOptions = WsfWeapon::FireOptions();
    fireOptions.mWeaponComponentName = weaponId;

    WsfWeapon::FireResult ret = weapon->Fire(GetSimulation().GetWallTime() + 1, fireTarget, fireOptions);
    ut::log::info() << "attackTargetFinish";
    return InterfaceError(1, "AttackTargetFinish");
}
ObserverControlInterface::InterfaceError ObserverControlInterface::HandleMsg_ControlSensor(Json::Value &data)
{
    WsfSimulation &simulation = this->GetSimulation();
    int pid = data["PlatformID"].asInt();
    WsfPlatform *pptr = simulation.GetPlatformByIndex(pid);
    if (!pptr)
        return InterfaceError(-1, "ControlSensorError_GetPlatFormError");

    std::string sensorID = data["SensorID"].asString();
    WsfSensor *sensor = static_cast<WsfSensor *>(pptr->FindComponent(sensorID));
    if (!sensor)
        return InterfaceError(-1, "ControlSensorError_GetSensorError");

    std::string action = data["Action"].asString();
    if (action == "Open")
    {
        ut::log::info() << "SensorOpen";
        GetSimulation().TurnPartOn(GetSimulation().GetWallTime(), sensor);
        ut::log::info() << "SensorOpenSuccess?" << sensor->IsClassActive();
    }
    else if (action == "Close")
    {
        ut::log::info() << "sensorClose";
        GetSimulation().TurnPartOff(GetSimulation().GetWallTime(), sensor);
        ut::log::info() << "SensorOpenSuccess?" << sensor->IsClassActive();
    }
    ut::log::info() << "SensorFinish";
    return InterfaceError(1, "ControlSensorFinish");
}
